﻿using System.Text.RegularExpressions;

namespace Toolkit.Lib.Services;

public static class IDVerificationService
{
    public static bool CheckId(string id)
    {
        const string p = @"^([1-6][1-9]|50)\d{4}(18|19|20)\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]";
        if (Regex.IsMatch(id,p))
            return CheckProv(id[..2])&& CheckDate(id[6..14]) && CheckCode(id);
        return false;
    }

    private static bool CheckProv(string id)
    {
        var proves = new[]
        {
            11, 12, 13, 14, 15,
            21, 22, 23,
            31, 32, 33, 34, 35, 36, 37,
            41, 42, 43, 44, 45, 46,
            50, 51, 52, 53, 54,
            61, 62, 63, 64, 65,
            71, 81, 82
        };
        return int.TryParse(id, out var a) && proves.Any(x => x == a);
    }

    private static bool CheckDate(string id)
    {
        var pattern = @"^(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)";
        if (!Regex.IsMatch(id, pattern)) return false;
        var year = id[..4];
        var month = id[4..6];
        var date = id[6..];
        return DateTime.TryParse($"{year}-{month}-{date}", out _);
    }

    private static bool CheckCode(string id)
    {
        var p = @"^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]";
        var factor = new[]{ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
        var parity = new object[]{ 1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2 };
        var code = id[^1].ToString();
        if (!Regex.IsMatch(id, p)) return false;
        var sum = 0;
        for(var i=0;i<17;i++)
            sum += int.Parse(id[i].ToString())*factor[i];
        return parity[sum % 11].ToString() == code.ToUpper();
    }

    public static bool CheckName(string name)
    {
        const string p = @"^(?:[\u4e00-\u9fa5]+)(?:●[\u4e00-\u9fa5]+)*$|^[a-zA-Z0-9]+\s?[\.·\-()a-zA-Z]*[a-zA-Z]+$";
        return Regex.IsMatch(name, p);
    }
}